﻿using System;
using SoftwareConsulting.BI11.NumericalMethods.Interfaces;

namespace SoftwareConsulting.BI11.NumericalMethods.Statistics
{
    /// <summary>
    /// Класс распределения Хи-квадрат (как случай Гамма-распределения)
    /// </summary>
    public sealed class ChiSquareDistribution : GammaDistribution
    {

        /// <summary>
        /// Конструктор класса
        /// </summary>
        /// <param name="freedomDegrees">степень свободы</param>
        public ChiSquareDistribution(int freedomDegrees) : 
            base( 0.5 * freedomDegrees, 2.0)
        {
        }

        /// <summary>
        /// Конструктор класса
        /// </summary>
        /// <param name="histogram">Гистограмма, из которой вытягиваются параметры по наилучшим предположениям</param>
        public ChiSquareDistribution(IHistogram histogram)
        {
            if (histogram.Minimum < 0)
                throw new ArgumentOutOfRangeException();                    
            int dof = (int)Math.Round(histogram.Average);
            if (dof <= 0)
                throw new ArgumentOutOfRangeException();                    
            DegreesOfFreedom = dof;
        }

        /// <summary>
        /// Возвращает уровень доверия
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public double GetConfidenceLevel(double x)
        {
            return x < 0 ? double.NaN : (1 - GetDistributionValue(x)) * 100;
        }

        /// <summary>
        /// Возвращает название распределения
        /// </summary>
        public override string Name
        {
            get 
            { 
                return "Chi square distribution"; 
            }
        }

        /// <summary>
        /// Возвращает/устанавливает параметры распределения
        /// </summary>
        public override double[] Parameters
        {
            get 
            { 
                return new double[] { AlphaShape * 2 }; 
            }
            set 
            { 
                SetParameters(value[0] * 0.5, 2); 
            }
        }

        /// <summary>
        /// Возвращает/устанавливает степень свободы
        /// </summary>        
        public int DegreesOfFreedom
        {
            get
            {
                return (int)AlphaShape * 2;
            }
            set 
            {
                base.SetParameters(0.5 * value, 2.0); 
            }
        }

        /// <summary>
        /// Возвращает как строку
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("{0} ({1:0.00})", Name, AlphaShape * 2);
        }
    }
}
